﻿#ifndef _RECORD_SET_H_
#define _RECORD_SET_H_
#include "record_proc.h"
#include "rec_schedule.h"
#ifdef _SPT_SIMULATOR_REC_
#include "MultiCHData.h"
#endif
#include "file_manager_arr.h"
#include "cross_com.h"

#include <vector>
using namespace std;

class CRecordSet
{
public:
    CRecordSet(CFile_manager_arr *pDiskCfg,int chnnNum);
	~CRecordSet();
	int InitParm();
	int Start();
	void Stop();
	void StopProc();
	void CloseRec();
	void StopRecordOfDisk(char * device);
	void StartRecord(int ch, int type, char *pText = NULL, uint32_t textLen = 0);
	void SetAlarmTime(int ch,int type,int recTimeSes);
	char *  GetRecFile(int ch);
	void DealAlarmRec();
	void StopRecord(int ch, int type,bool bCloseFile = false,bool bForce = false);
	void PauseRecord(int ch);
	int  GetRecordType(int ch);
	void ProcStatus();
	bool IsOpenManualRec(int ch);
	void SetEnable(int ch, uint16_t bEnable);
	
	//支持音频录制
	void SetEnableAudio(int ch, uint16_t bEnable);
	int  GetAudioRecEnable(int ch);

	void ChanageType(int ch,int type);
	void SetFileType(int ch, int fileType);
	void SetRecordAudio(int ch, bool bWithAudio);
	void SetRecycleRecord(bool bRecycle);
	void SetPrepareRec(bool bEnable,int nSecs);
	void SetRedundancyRec(int ch, bool bRedundancy);
	void SetPreAlarmTime(int ch, uint16_t preAlarmTime);
	void SetPostAlarmTime(int ch, int type, uint16_t postAlarmTime);
 	void SetSchedule(int ch,const SCHDULE_REC& schedule);
 	void GetSchedule(int ch,SCHDULE_REC* pSchedule);
	void SetReducDisk(uint16_t *pDiskIndex, uint32_t reducDiskNum);
	void SetResolution(int width,int height,int channel);
	//设置磁盘和通道的关系并变换磁盘群组
	void SetStartRecordDisk(int diskIdx);
	bool IsOpenManualRecord(int ch);
	int IsContentRecord(int ch);
	bool IsNeedDiskFullAlarm();
	bool IsHaveChannelStopRec();
	bool IsChReocrding(int ch);;
	bool IsRecording(char * dev);
	void DealRecordStatus();
 	void CallbackRecStatus(bool bLost = false);
	void CallbackRecStatus(int ch , int recType);
	void CallbackDiskStatus();
	void CallbackDiskFull(bool bEnable = true);
	void CallbackDiskError(int diskNO);
	int  RestartRecord();
	int  SetRecDataSource(int ch,int dataSourceID);
	int  CountWtSpeed(time_t now ,int countSecs = 5);
	bool  CheckDiskFull(time_t now,int countSecs = 3);
	int WriteGPSInfo(int ch, uchar_t * gpsInfo,int gpsInfoSize);
	int GetCurFrmTm(int ch,int64_t & frmTm);
	void SetVideoParm(int ch,int width,int height,int frame_rate);
	void SetAudioParm(int ch,int audio_channels, long rate, int bits, int format);

	bool                m_bDiskScanning;        //是否正在扫描当中
	bool				m_bThreadLive;		//
	bool				m_bTimeTheadLive;	//计划时间线程是否在运行
	int	                m_diskFullCnt;		//磁盘满了
	uint32_t            m_lastFrmSz;		//最后一帧的大小
	static uint32_t		m_procBIT;			//状态位最多支持16种状态


    enum PRPC_STATUS
	{
		PROC_NONE			=  0,
		PROC_WT_BADSEC		=  0x01,
		PROC_DISK_CHECK		=  0x02,
		PROC_DISK_ADDDISK	=  0x04,
		PROC_DISK_WAKEUP 	=  0x08,
		PROC_DISK_FULL		=  0x10,
		PROC_NO_RECFILE     =  0x20,
		PROC_DISK_LOST		=  0x40,
		PROC_DISK_ERROR     =  0x80,
		PROC_DISK_1STREPORT	=  0x100,
		PROC_RECORD_STATUS  =  0x200,//处理通道的录像状态
		PROC_COMMON_STATUS  =  0x400,//回调通用的回调状态
	};
#ifdef _SUPPORT_64_CH_
	int64_t				m_recStatusBIT;			//超过32路的tg产品
#else
	int32_t				m_recStatusBIT;			//最大32路产品
#endif
	int WriteFrameDataProc(int ch,uchar_t * frameBuf, int bufSize );
	int GetOneFrameData(int ch, uchar_t * frameBuf, int size);
	int WriteOneFrameData(int ch, int size);
	int ProcStartRecord(int ch ,int type,int64_t time);

	typedef struct
	{
		uint16_t	recv;
		uint16_t	diskIndex;
		CRecordSet	*pRecordSet;
	}DATA_THREAD_PARAM;

	typedef struct
	{
		uint16_t	bReduc;				//是否为冗余磁盘
		uint16_t	bActive;			//是否为激活状态
		uint16_t	group;				//磁盘组

		bool			bDataProc;
		cross_thread_t	dataProcThreadID;
		cross_lock_t	lock;
		CRecord1CHProc	*pRecDataProc[MAX_CAMERA_NUM];		//操作对象指针
	}RECORD_DISK;	//录像磁盘

	typedef struct
	{
		uint16_t	bActive;			//激活开关
		uint16_t	bEnable;			//是否开启录像
		uint16_t	bWithAudio;			//是否录音频
		uint16_t	bRedundancy;		//是否冗余

		uint16_t    bPrepare;			//是否预录像
		uint16_t    nPrepareSecs;		//预录像时间
		uint16_t    bRecConnectTodisk;

		CRecord1CHProc	*pRecDataProc;		//普通录像

	}RECORD_CAMERA; //录像通道

	typedef struct _RECORD_CTRL_
	{
		uint16_t		inStatus;		//STREAM_STATUS 0:NONE_DATA 1:
		uint16_t		preHoldTime;
		int				recType;
		int				recTypeBak;
		int				endType;

		//特性录像时，需要界面传入指定录像的时间大小
		time_t			startIOAlarm;
		time_t			startMontim;
		time_t			startShleter;
		time_t			startBehavior;

		int16_t			montionTm;			// FS_RECORD_MOTION		= 0x0004,	    //移动侦测报警录像
		int16_t			ioAlarmTm;			// FS_RECORD_IOALARM	= 0x0008,		//传感器报警录像
		int16_t			shelterTm;			// FS_RECORD_SHELTER	= 0x0010,		//遮挡报警录像
		int16_t			behaviorTm;			// FS_RECORD_BEHAVIOR 	= 0x0020,		//行为分析录像

		CSchedule	   *pSchedule;

	}RECORD_CTL_PARAM;

protected:
	static int PUB_THREAD_CALL DataProcThread(void *pParam);
	static int PUB_THREAD_CALL TimerThread(void *pParam);


	bool                m_bNeedStop;
	bool				m_bPause;

	uint16_t			m_diskNum;			//实际可用磁盘数目
	uint16_t			m_maxDiskNum;		//最大磁盘数目
	uint16_t			m_chnnNum;			//通道数目

	CFile_manager_arr	*m_pIndexSet;		//索引集合
	RECORD_CAMERA		*m_pRecordCamera;   //录像通道

	bool				m_bPrepare;			//是否预录像
	uint16_t			m_nPrepareSecs;		//预录像时间

	cross_thread_t      m_dataThdID;
	cross_thread_t      m_timeThdID;

	vector<RECORD_CTL_PARAM> m_vecRecParam;

public:
	static   int MANUAL_SWITCH;			//手动录像开关

	//测试写入速度相关参数
	uint32_t    m_wt_data;
	uint32_t    m_wt_bak;
	time_t      m_lastCoutTime;
	time_t      m_lastCeckDiskFullTm;
	uint32_t    m_wt_speed;
	FIFO_BUF_INFO m_curFrm;;
	uint32_t    m_show_cnt;
	CFrmUtility m_frmTool;
	bool        m_bEvtStop; // 是否产生紧急录像结束时需要强制关闭文件
public:
	CFile_manager_arr * GetIndexSet()
	{
		return m_pIndexSet;
	}
	int GetThreadID()
	{
		return (int)m_dataThdID;
	}
	bool IsPrepareRec()
	{
		return m_bPrepare;
	}

	bool IsCyCleRec()
	{
		return (bool)m_pRecordCamera[0].pRecDataProc->GetCycleStatus();
	}

	bool IsStartRecordThd()
	{
		return !m_bNeedStop;
	}
	int  GetWtSpeed()
	{
		return m_wt_speed;
	}
	uint32_t GetWritePercent(int ch)
	{
		if(ch < m_chnnNum)
		{
			return m_pRecordCamera[ch].pRecDataProc->GetCurFilePercent();
		}
		else
		{
			return 0;
		}
	}

	uint32_t GetFileIndex(int ch)
	{
		if(ch < m_chnnNum)
		{
			return m_pRecordCamera[ch].pRecDataProc->GetFileIndex();
		}
		else
		{
			return 0;
		}
	}

	uint32_t GetCurRecordSN(int ch)
	{
		if(ch < m_chnnNum)
		{
			return m_pRecordCamera[ch].pRecDataProc->GetCurRecordSN();
		}
		else
		{
			return 0;
		}
	}

	CRecWriteBase * GetRecWriter(int ch)
	{
		if(ch < m_chnnNum)
		{
			return m_pRecordCamera[ch].pRecDataProc->GetRecWriter();
		}
		else
		{
			return NULL;
		}
	}

	int GetCacheWater(int ch)
	{
		if(ch < m_chnnNum)
		{
			return m_pRecordCamera[ch].pRecDataProc->GetCacheWater();
		}
		else
		{
			return 0;
		}
	}


	void SetMaxCHNum(int chnnNum)
	{
		m_chnnNum = chnnNum;
	}
	int  GetMaxCHNum()
	{
		return m_chnnNum;
	}
	int RecordThreadLive()
	{
		return m_bThreadLive;
	}

	int GetChRate(int ch)
	{
		if(ch < m_chnnNum)
			return m_pRecordCamera[ch].pRecDataProc->GetRate();
		else
			return 0;
	}
	bool IsNeedStop()
	{
		return m_bNeedStop;
	}
	RECORD_CTL_PARAM* GetParmCtrl(int ch)
	 {
		 return &m_vecRecParam[ch];
	 }
private:
	CCross_Lock		  m_lock;
};
extern CRecordSet * g_pRecSet;
enum STREAM_STATUS
{
	STREAM_NONE	   = 0,
	STREAM_GETDATA = 1,
	STREAM_DATALOST= 2,
};
#endif	//_RECORD_SET_H_
